#include "Cryptoer.h"
#include "Poco\Util\LayeredConfiguration.h"
#include <Poco\File.h>
#include <Poco\Path.h>
#include <Poco\FileStream.h>
#include <Poco\Util\Application.h>
#include "Util.h"
using Poco::Path;
using Poco::File;
using Poco::FileInputStream;
using Poco::FileOutputStream;
using Poco::Util::Application;
Cryptoer::Cryptoer()
{
	Application& app = Application::instance();
	this->crypto = app.config().getString("crypto");
	this->pwd = app.config().getString("pwd");
	CipherKey key(crypto, pwd);
	pCipher = CipherFactory::defaultFactory().createCipher(key);
}


Cryptoer::~Cryptoer()
{
}

std::string Cryptoer::encodeContents(const std::string &fn)
{
	std::string contents = Util::readContents(fn);
	Path path = Path(fn);
	std::string base = path.getBaseName();
	std::string ext = path.getExtension();
	return encodeContents(contents, base, ext);
}

std::string Cryptoer::decodeContents(const std::string &fn)
{
	std::string contents = Util::readContents(fn);
	Path path = Path(fn);
	std::string base = path.getBaseName();
	std::string ext = path.getExtension();
	return decodeContents(contents, base, ext);
}
std::string Cryptoer::encodeContents(const File & f)
{
	return encodeContents(f.path());
}
std::string Cryptoer::decodeContents(const File & f)
{
	return decodeContents(f.path());
}
std::string Cryptoer::rawDecode(const std::string & content)
{
	return pCipher->decryptString(content, Cipher::ENC_BASE64);
	
}
std::string Cryptoer::rawEncode(const std::string & contents)
{
	return pCipher->encryptString(contents, Cipher::ENC_BASE64_NO_LF);
}
std::string Cryptoer::rawDecodeNonBase64(const std::string & contents)
{
	return pCipher->decryptString(contents);
}
std::string Cryptoer::rawEncodeNonBase64(const std::string & contents)
{
	return pCipher->encryptString(contents);
}
void Cryptoer::rawDecodeNonBase64(std::istream & source, std::ostream & sink)
{
	 pCipher->decrypt(source,sink);
}
void Cryptoer::rawEncodeNonBase64(std::istream & source, std::ostream & sink)
{
	 pCipher->encrypt(source,sink);
}
void Cryptoer::encodeFile(const std::string & ifn, const std::string & ofn)
{
	std::string oc = encodeContents(ifn);
	Util::writeContents(ofn, oc);
}
void Cryptoer::decodeFile(const std::string & ifn, const std::string & ofn)
{
	std::string oc = decodeContents(ifn);
	Util::writeContents(ofn, oc);
}
void Cryptoer::encodeFile(const std::string & ifn)
{
	std::string ofn = Util::getSrcsFileName(ifn);
	encodeFile(ifn, ofn);
}
void Cryptoer::decodeFile(const std::string & ifn)
{
	std::string ofn = Util::getSrcFileName(ifn);
	decodeFile(ifn, ofn);
}
void Cryptoer::encodeFile(const Poco::File & ifn)
{
	encodeFile(ifn.path());
}
void Cryptoer::decodeFile(const Poco::File & ifn)
{
	decodeFile(ifn.path());
}

 std::string Cryptoer::replaceAll(const std::string& str, const std::string& from, const std::string& to) {
	size_t start_pos = 0;
	std::string res = str;
	while ((start_pos = res.find(from, start_pos)) != std::string::npos) {
		res.replace(start_pos, from.length(), to);
		start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
	}
	return res;
}


std::string Cryptoer::processGlobalMacro(std::string raw, std::string file_base, std::string file_ext) {
	std::string res = replaceAll(raw, "%FILE_BASE%", file_base);
	res = replaceAll(res, "%FILE_EXT%", file_ext);
	return res;
}